/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 */

package com.xinyue.game.gateway.server.websocket;

import com.google.common.util.concurrent.RateLimiter;
import com.xinyue.game.gateway.common.GameGatewayConfig;
import com.xinyue.game.gateway.local.DispatcherRequestHandler;
import com.xinyue.game.gateway.local.GameChannelConfirmHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

/**
 * web socket channel实始化器，用于创建支持web socket连接的游戏服务
 *
 * @author 王广帅
 * @since 2021/1/24 17:20
 */
public class WebSocketServerChannelInitializer extends ChannelInitializer<Channel> {

    private Logger logger = LoggerFactory.getLogger(WebSocketServerChannelInitializer.class);
    private ApplicationContext context;
    /**
     * 全局请求QPS限制器
     */
    private RateLimiter globalLimiter;

    /**
     * 构造方法
     *
     * @param context spring 容器
     */
    public WebSocketServerChannelInitializer(ApplicationContext context) {
        this.context = context;
        GameGatewayConfig gameFrameworkConfig = context.getBean(GameGatewayConfig.class);
        globalLimiter = RateLimiter.create(gameFrameworkConfig.getGlobalRequestQps());
    }

    /**
     * 初始化一个netty channel信息
     *
     * @param ch 当前创建的channel
     */
    @Override
    protected void initChannel(Channel ch) {
        try {
            GameGatewayConfig gameServerConfig = context.getBean(GameGatewayConfig.class);
            ch.pipeline().addLast(new HttpServerCodec());
            ch.pipeline().addLast(new ChunkedWriteHandler());
            ch.pipeline().addLast(new HttpObjectAggregator(gameServerConfig.getMaxFrameLength()));
            ch.pipeline().addLast(new WebSocketServerProtocolHandler("/request"));
            ch.pipeline().addLast(new WebSocketDecoderHandler());
            ch.pipeline().addLast(new WebSocketEncoderHandler());
            // 认证连接
            GameChannelConfirmHandler channelConfirmHandler = context.getBean(GameChannelConfirmHandler.class);
            ch.pipeline().addLast(channelConfirmHandler);
            DispatcherRequestHandler dispatcherRequestHandler = context.getBean(DispatcherRequestHandler.class);
            ch.pipeline().addLast(dispatcherRequestHandler);
        } catch (Throwable e) {
            logger.error("初始化channel异常", e);
        }

    }
}
